package com.sz.app.customer.web.security;

import com.sz.biz.app.web.security.AbstractCredentialsMatcher;
import com.sz.biz.app.web.security.MyAuthenticationInfo;
import com.sz.biz.common.constants.CustomerConstants;
import com.sz.biz.common.customer.entity.CusCustomer;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.common.customer.service.CustomerService;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.common.base.constants.UserActions;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalManager;
import com.sz.app.customer.constants.ModuleNames;
import com.sz.app.customer.exception.CustomerAuthenticationException;
import com.sz.app.customer.exception.CustomerUpdatePasswordException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;


public class CustomerHashedCredentialsMatcher extends
        AbstractCredentialsMatcher {

    @Autowired
    CustomerUserService customerUserService;

    @Autowired
    CustomerService customerService;

    @Autowired
    private PrincipalManager principalManager;

    public CustomerHashedCredentialsMatcher(CacheManager cacheManager) {
        super(cacheManager);
    }

    @Override
    protected void lockUser(int accountId, String accountName) {
        List<Integer> accountList = new ArrayList<>();
        accountList.add(accountId);
        customerUserService.lockCustomer(accountList);

        passwordRetryCache.remove(accountName);
        PrincipalLogUtils.addOperationLog(ModuleNames.CUSTOMER, ModuleNames.CUSTOMER_LOGIN, UserActions.LOCK,
                accountName + "输入错误次数过多，被系统锁定");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token,
                                      AuthenticationInfo info) {

        if (!(info instanceof MyAuthenticationInfo)) {
            throw new RuntimeException("No supported AuthenticationInfo");
        }
        MyAuthenticationInfo myInfo = (MyAuthenticationInfo) info;

        int accountId = myInfo.getAccountId();
        String accountName = myInfo.getAccountName();

        //对比密码
        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            //如果正确，清除之前连续错误的计数
            passwordRetryCache.remove(accountName);

            String loginName = (String) token.getPrincipal();
            CusUser user = customerUserService.findByAccountName(loginName);

            CusCustomer customer = customerService.findCustomerById(user.getRefCustomerId());
            if (customer == null) {
                throw new UnknownAccountException("error ref customerId");//没找到帐号
            }
            //需要认证
            if (customer.getAuthStatus() == null || customer.getAuthStatus().compareTo(CustomerConstants.AuthStatus.PASS) != 0) {
                if (user.getIsSystem()) {
                    throw new CustomerAuthenticationException("主账户需要认证");
                }
                else {
                    throw new LockedAccountException("error ref customerId");
                }
            }
            if (customer.getLocked() || customer.getDeleted()) {
                throw new LockedAccountException("error ref customerId");
            }
            boolean mainAccountIsLocked = customerUserService.checkMainAccountLockedStatus(loginName);
            if (user.getIsLocked() || mainAccountIsLocked) {
                throw new LockedAccountException();
            }
            if (user.getNeedResetPwd() != null && user.getNeedResetPwd() == true) {
                throw new CustomerUpdatePasswordException("need reset password");
            }
            myInfo.setProperty("AssociatedAccountId", customer.getId());
            myInfo.setProperty("AssociatedAccountName", customer.getCode()); // 以code为account name
            principalManager.setupPrincipal(myInfo.getAppDomain(), accountId,
                    myInfo.getAccountName(), myInfo.getProperties());
            return true;
        }
        return false;
    }

    @Override
    protected String getPasswordRetryCacheName() {
        return "passwordRetryCache-customer";
    }
}
